﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace GraphosData
{


	public class GraphReader
	{

		private Graph graph;
		private Person person;
		//private Person personOther;

		private XDocument xDoc;
		private XElement xRoot;

		private string strId = "id";
		private string strFirstName = "firstname";
		private string strLastName = "lastname";
		private string strGender = "gender";
		private string strRel = "relationships";
		private string strRootName;
		private string strFileName;

		Dictionary<string, Person> dictPeople;
		//Relation relationType;

		public GraphReader()
		{
			strRootName = "people";
			graph = new Graph();
			dictPeople = new Dictionary<string, Person>();
		}

		//public functions
		public Graph OpenFile(string filename, string rootname)
		{
			try
			{
				xDoc = XDocument.Load(filename);
			}
			catch(Exception e)
			{
				Console.WriteLine(e.Message);
				return null;
			}

			xRoot = xDoc.Element(rootname);

			Dictionary<Person, Dictionary<string, string>> dictRelationships = new Dictionary<Person, Dictionary<string, string>>();

			foreach (XElement p in xRoot.Elements())
			{
				person = new Person();
				person.FirstName = (string)p.Element(strFirstName);
				person.ID = (string)p.Element(strId);
				person.LastName = (string)p.Element(strLastName);
				person.Gender = (string)p.Element(strGender) == "M" ? Gender.Male : Gender.Female;

				try
				{
					dictPeople[person.ID] = person;
				} //end try
				catch (Exception e)
				{
					Console.WriteLine(e.Message);
					throw;
				} //end catch

				try
				{
					graph.AddNode(person);
				}
				catch (Exception e)
				{
					Console.WriteLine(e.Message);
				}
				try
				{
					dictRelationships.Add(person, new Dictionary<string, string>());
				} //end try
				catch (Exception e)
				{
					Console.WriteLine("Exception: {1} for Person: {0}", person.FirstName, e.Message);
					throw;
				} //end catch
				
				foreach (XElement personElement in p.Element(strRel).Elements())
				{
					try
					{
						dictRelationships[person].Add((string)personElement.Element(strId), (string)personElement.Element("type"));
					} //end try
					catch (Exception e)
					{
						Console.WriteLine("Exception {3} for person {0} and relationship {1} of type {2}", person.FirstName, (string)personElement.Element(strId), (string)personElement.Element("type"),e.Message);
						throw;
					} //end catch
				
				}

			}

			foreach (Person p in dictPeople.Values)
			{
				foreach (var pair in dictRelationships[p])
				{
					Person pRel = dictPeople[pair.Key];
					Relation relationType;
					switch (pair.Value)
					{

						case "son":
							relationType = Relation.Son;
							break;
						case "daughter":
							relationType = Relation.Daughter;
							break;
						case "mother":
							relationType = Relation.Mother;
							break;
						case "father":
							relationType = Relation.Father;
							break;
						case "sister":
							relationType = Relation.Sister;
							break;
						case "brother":
							relationType = Relation.Brother;
							break;
						case "wife":
							relationType = Relation.Wife;
							break;
						case "husband":
							relationType = Relation.Husband;
							break;
						case "apostle":
							relationType = Relation.Apostle;
							break;
                        case "disciple":
                            relationType = Relation.Disciple;
                            break;
						case "grandson":
							relationType = Relation.Grandson;
							break;
						case "family":
							relationType = Relation.Family;
							break;
						case "maidservant":
							relationType = Relation.MaidServant;
							break;
						case "grandfather":
							relationType = Relation.GrandFather;
							break;
						case "concubine":
							relationType = Relation.Concubine;
							break;
						case "concubine of":
							relationType = Relation.ConcubineOf;
							break;
						case "uncle":
							relationType = Relation.Uncle;
							break;
						case "aunt":
							relationType = Relation.Aunt;
							break;
						case "nephew":
							relationType = Relation.Nephew;
							break;
						case "niece":
							relationType = Relation.Niece;
							break;
						case "son-in-law":
							relationType = Relation.SonInLaw;
							break;
						case "father-in-law":
							relationType = Relation.FatherInLaw;
							break;
						case "daughter-in-law":
							relationType = Relation.DaughterInLaw;
							break;
						case "mother-in-law":
							relationType = Relation.MotherInLaw;
							break;
						default:
							relationType = Relation.Unknown;
							break;
					}
					//if (relationType == Relation.Concubine || relationType == Relation.Daughter || relationType == Relation.GrandDaughter ||
					//    relationType == Relation.GrandMother || relationType == Relation.MaidServant || relationType == Relation.Mother ||
					//    relationType == Relation.Sister || relationType == Relation.Wife)
					//    //pRel.Gender = Gender.Female;
					graph.AddEdge(p, pRel, relationType);
				}
			}

			//foreach (XElement p in xRoot.Elements())
			//{
			//   person = dictPeople[(string)p.Element(strId)];

			//   foreach (XElement relatedpeople in p.Element(strRel).Elements())
			//   {
			//      personOther = dictPeople[(string)relatedpeople.Element(strId)];

			//      string relType = (string)relatedpeople.Element("type");
			//      switch (relType)
			//      {

			//         case "son":
			//            relationType = Relation.Son;
			//            break;
			//         case "daughter":
			//            relationType = Relation.Daughter;
			//            break;
			//         case "mother":
			//            relationType = Relation.Mother;
			//            break;
			//         case "father":
			//            relationType = Relation.Father;
			//            break;
			//         case "sister":
			//            relationType = Relation.Sister;
			//            break;
			//         case "brother":
			//            relationType = Relation.Brother;
			//            break;
			//         case "wife":
			//            relationType = Relation.Wife;
			//            break;
			//         case "husband":
			//            relationType = Relation.Husband;
			//            break;
			//         case "apostle":
			//            relationType = Relation.Apostle;
			//            break;
			//         case "grandson":
			//            relationType = Relation.Grandson;
			//            break;
			//         case "family":
			//            relationType = Relation.Family;
			//            break;
			//         case "maidservant":
			//            relationType = Relation.MaidServant;
			//            break;
			//         case "concubine":
			//            relationType = Relation.Concubine;
			//            break;
			//         default:
			//            relationType = Relation.Unknown;
			//            break;
			//      }
			//      graph.AddEdge(person, personOther, relationType);
			//   }
			//}
			return graph;
		}

		public Graph OpenFile(string filename)
		{
			return OpenFile(filename, strRootName);
		}


		//properties
		public string RootName
		{
			get { return strRootName; }
			set { strRootName = value; }
		}

	}
}
